package com.ctw.tinyservices.id.sdk.segment;

import com.alibaba.fastjson.JSON;
import com.ctw.tinyservices.id.common.enums.state.IdLifecycleState;
import com.ctw.tinyservices.id.common.utils.LogUtils;
import com.ctw.tinyservices.id.core.IdGenerator;
import com.ctw.tinyservices.id.sdk.AbstractIdSdk;
import com.ctw.tinyservices.id.common.exception.HttpException;
import com.ctw.tinyservices.id.sdk.enums.HttpMethodEnum;
import com.ctw.tinyservices.id.sdk.segment.service.IdSegmentHttpService;
import com.ctw.tinyservices.id.sdk.util.OkHttpUtils;
import com.ctw.tinyservices.id.sdk.util.ServerLoadBalanceUtils;
import com.ctw.tinyservices.id.core.segment.generator.IdSegmentGenerator;
import com.ctw.tinyservices.id.core.segment.buffer.SegmentBuffer;
import com.google.common.base.Strings;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author TongWei.Chen 2022/3/21 20:53
 *
 * IdSegmentSdk
 **/
public class IdSegmentSdk extends AbstractIdSdk {
    private static Map<String /* bizType */, SegmentBuffer> segmentBufferMap = new ConcurrentHashMap<>();
    private Object monitor = new Object();
    private IdGenerator idSegmentGenerator;

    /**
     * 单例
     */
    private IdSegmentSdk(String location) {
        this.location = location;
    }

    private volatile static IdSegmentSdk singleton;
    public static IdSegmentSdk getInstance(String location) {
        if (singleton == null) {
            synchronized (IdSegmentSdk.class) {
                if (singleton == null) {
                    singleton = new IdSegmentSdk(location);
                }
            }
        }
        return singleton;
    }

    @Override
    public Long getId(String bizType) {
        while (idSegmentGenerator.getState() == IdLifecycleState.START) {
            SegmentBuffer buffer = segmentBufferMap.get(bizType);
            if (null != buffer) {
                return ((IdSegmentGenerator) idSegmentGenerator).getIdFromSegmentBuffer(buffer);
            }

            synchronized (monitor) {
                if (null == segmentBufferMap.get(bizType)) {
                    StringBuilder url =
                            new StringBuilder(ServerLoadBalanceUtils.getUrl(HttpMethodEnum.GET_SEGMENT_BUFFER))
                                    .append(HttpMethodEnum.getSegmentBufferParam(bizType));
                    String response = OkHttpUtils.get(url.toString(), null, ServerLoadBalanceUtils.getHeader());
                    if (Strings.isNullOrEmpty(response)) {
                        throw new HttpException(url.toString(), bizType);
                    }
                    buffer = JSON.parseObject(response, SegmentBuffer.class);
                    // cache
                    segmentBufferMap.put(bizType, buffer);
                }
            }
        }
        LogUtils.warn(IdSegmentSdk.class, "server is closed, and state is [{}]", idSegmentGenerator.getState());
        return null;
    }

    @Override
    protected void doInit() {
        super.doInit();

        idSegmentGenerator = new IdSegmentGenerator(new IdSegmentHttpService());
        idSegmentGenerator.setState(IdLifecycleState.START);
    }
}
